package com.cakebackoffice;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import com.cakebackoffice.Model.CatalogCategory;
import com.cakebackoffice.clientsoap.CakeBackOfficeSoapClient;
import com.cakebackoffice.clientsoap.Exception.SoapClientException;
import com.cakebackoffice.clientsoap.Exception.SoapComException;
import com.cakebackoffice.clientsoap.contract.*;
import com.cakebackoffice.database.*;

import java.util.ArrayList;
import java.util.List;

public abstract class SyncTaskManager {

    public static boolean syncStores(Context context, List<Store> stores) {

        OurSQLiteOpenHelper ourSQLiteOpenHelper = new OurSQLiteOpenHelper(context);

        ourSQLiteOpenHelper.truncateTable(StoreTable.getInstance());
        ourSQLiteOpenHelper.close();

        for (Store store : stores) {
            new com.cakebackoffice.Model.Store(context, store).saveToDatabase(context);
        }
        return true;
    }

    public static boolean syncCatalog(Context context, Catalog catalog) {
        OurSQLiteOpenHelper ourSQLiteOpenHelper = new OurSQLiteOpenHelper(context);

        ourSQLiteOpenHelper.truncateTable(new DatabaseTable[]{
                OrderTable.getInstance(),
                UnitarySaleTable.getInstance(),
                ProductTable.getInstance(),
                MenuTypeTable.getInstance()
        });
        ourSQLiteOpenHelper.close();

        if (catalog.products != null)
            for (ProductType productType : catalog.products) {
                new com.cakebackoffice.Model.ProductType(context, productType).saveToDatabase(context);
            }
        if (catalog.categories != null)
            for (ProductCategory productCategory : catalog.categories) {
                new com.cakebackoffice.Model.CatalogCategory(context, productCategory).saveToDatabase(context);
            }
        if (catalog.categories != null)
            for (ProductCategory productCategory : catalog.categories) {
                new com.cakebackoffice.Model.CatalogCategory(context, productCategory).saveToDatabase(context);
            }

        return true;
    }


    public static boolean syncOrder(Context context, List<Order> orderList) {

        OurSQLiteOpenHelper ourSQLiteOpenHelper = new OurSQLiteOpenHelper(context);

        ourSQLiteOpenHelper.truncateTable(new DatabaseTable[]{
                OrderTable.getInstance(),
                UnitarySaleTable.getInstance(),
        });
        ourSQLiteOpenHelper.close();

        for (Order order : orderList) {
            new com.cakebackoffice.Model.Order(context, order).saveToDatabase(context);
        }
        return true;
    }

    public static void updateStoreOnServer(final com.cakebackoffice.Model.Store selectedStore) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    serveur.updateStore(new com.cakebackoffice.clientsoap.contract.SimpleStore(selectedStore));
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }

    public static void insertStoreOnServer(final Context context, final com.cakebackoffice.Model.Store store) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    store.setRemoteID(serveur.insertStore(new com.cakebackoffice.clientsoap.contract.SimpleStore(store)).longValue());
                    store.saveToDatabase(context);
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }

    public static void insertProductTypeToServer(final Context context, final com.cakebackoffice.Model.ProductType productType, final CatalogCategory actualCategory) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    productType.setRemoteID(serveur.insertProductType(new com.cakebackoffice.clientsoap.contract.ProductType(productType)).longValue());
                    productType.saveToDatabase(context);
                    serveur.addProductTypeToCategory(productType.getRemoteID().intValue(), actualCategory.getRemoteID().intValue());
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }

    public static void updateProductTypeToServer(final com.cakebackoffice.Model.ProductType selectedProduct) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    serveur.updateProductType(new com.cakebackoffice.clientsoap.contract.ProductType(selectedProduct));
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }).start();
    }

    public static void InsertMenuTypeToServer(final com.cakebackoffice.Model.MenuType menuType, final CatalogCategory actualCategory) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    serveur.insertMenuType(new com.cakebackoffice.clientsoap.contract.MenuType(menuType));
                    //serveur.updateProductCategory(new ProductCategory(actualCategory));
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }).start();
    }

    public static void deleteMenuTypeToServer(final com.cakebackoffice.Model.MenuType object) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    serveur.deleteMenuType(Integer.valueOf((object).getRemoteID().toString()));
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }

    public static void deleteProductTypeToServer(final com.cakebackoffice.Model.ProductType object) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    serveur.deleteProductType((object).getRemoteID().intValue());
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }


    public static void insertCategoryToServer(final Context context, final CatalogCategory childCategory, final CatalogCategory actualCategory) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    childCategory.setRemoteID(serveur.insertProductCategory(new com.cakebackoffice.clientsoap.contract.ProductCategory(childCategory)).longValue());
                    childCategory.saveToDatabase(context);
                    serveur.addProductCategoryToCategory(actualCategory.getRemoteID().intValue(), childCategory.getRemoteID().intValue());
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }

    public static void deleteProductCategoryToServer(final CatalogCategory object) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient serveur = new CakeBackOfficeSoapClient();
                try {
                    serveur.deleteProductCategory(object.getRemoteID().intValue());
                } catch (SoapComException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                } catch (SoapClientException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }

            }
        }).start();
    }

    public static void deleteOrderFromServer(final com.cakebackoffice.Model.Order orderToDelete) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                CakeBackOfficeSoapClient server = new CakeBackOfficeSoapClient();
                try {
                    server.deleteOrder(Integer.valueOf(orderToDelete.getRemoteID().toString()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static class storeUpdate extends AsyncTask<Integer, Integer, Integer> {
        ProgressDialog progressDialog;
        Context context;

        public storeUpdate(Context context) {
            this.context = context;
        }

        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }

        @Override
        protected Integer doInBackground(Integer... voids) {
            try {
                CakeBackOfficeSoapClient server = new CakeBackOfficeSoapClient();
                List<Store> stores = server.getStores();
                SyncTaskManager.syncStores(context, stores);

            } catch (Exception e) {

                return 0;
            }

            return 100;
        }

        @Override
        protected void onPreExecute() {
            progressDialog = ProgressDialog.show(getContext(), "Récupération des magasins", "Communication en cours...");
        }

        @Override
        protected void onPostExecute(Integer i) {
            progressDialog.dismiss();
            if (i == 0) {
                new AlertDialog.Builder(context).setMessage("Impossible de Synchroniser avec le serveur")
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.dismiss();
                            }
                        }).setPositiveButton("Dare to ... Try Again", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        new storeUpdate(context).execute();
                    }
                }).show();
            }
        }
    }

    public static class catalogUpdate extends AsyncTask<Integer, Integer, Integer> {
        ProgressDialog progressDialog;
        Context context;

        public catalogUpdate(Context context) {
            this.context = context;
        }

        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }

        @Override
        protected Integer doInBackground(Integer... voids) {
            try {
                OurSQLiteOpenHelper ourSQLiteOpenHelper = new OurSQLiteOpenHelper(context);
                CakeBackOfficeSoapClient server = new CakeBackOfficeSoapClient();

                Catalog catalog = server.getAbsoluteCatalog();
                SyncTaskManager.syncCatalog(context, catalog);

            } catch (Exception e) {

                return 0;
            }

            return 100;
        }

        @Override
        protected void onPreExecute() {
            progressDialog = ProgressDialog.show(getContext(), "Récupération du Catalogue", "Communication en cours...");
        }

        @Override
        protected void onPostExecute(Integer i) {
            progressDialog.dismiss();
            if (i == 0) {
                new AlertDialog.Builder(context).setMessage("Impossible de Synchroniser avec le serveur")
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.dismiss();
                            }
                        }).setPositiveButton("Dare to ... Try Again", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        new catalogUpdate(context).execute();
                    }
                }).show();
            }
        }
    }

    public static class orderUpdate extends AsyncTask<Integer, Integer, Integer> {
        ProgressDialog progressDialog;
        Context context;

        public orderUpdate(Context context) {
            this.context = context;
        }

        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }

        @Override
        protected Integer doInBackground(Integer... voids) {
            try {
                CakeBackOfficeSoapClient server = new CakeBackOfficeSoapClient();

                List<Order> orderList = new ArrayList<Order>(0);
                if (com.cakebackoffice.Model.Store.getLocalStore(context) != null)
                    orderList = server.getFollowingOrderList(Integer.parseInt(com.cakebackoffice.Model.Store.getLocalStore(context).getRemoteID().toString()));
                SyncTaskManager.syncOrder(context, orderList);
                return orderList.size() + 100;

            } catch (Exception e) {

                return 0;
            }

        }

        @Override
        protected void onPreExecute() {
            progressDialog = ProgressDialog.show(getContext(), "Recuperation des Commandes", "Communication en cours...");
        }

        @Override
        protected void onPostExecute(Integer i) {
            if (progressDialog != null && progressDialog.isShowing())
                progressDialog.dismiss();
            if (i == 0) {
                new AlertDialog.Builder(context).setMessage("Impossible de Synchroniser avec le serveur")
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.dismiss();
                            }
                        }).setPositiveButton("Dare to ... Try Again", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        new orderUpdate(context).execute();

                    }
                }).show();
            }
        }
    }


    public static class ApplicationInitialisation extends AsyncTask<Integer, Integer, Integer> {
        ProgressDialog progressDialog;
        Context context;

        public ApplicationInitialisation(Context context) {
            this.context = context;
        }

        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }

        @Override
        protected Integer doInBackground(Integer... voids) {
            try {
                OurSQLiteOpenHelper ourSQLiteOpenHelper = new OurSQLiteOpenHelper(context);
                CakeBackOfficeSoapClient server = new CakeBackOfficeSoapClient();

                List<Store> stores = server.getStores();
                Catalog catalog = server.getAbsoluteCatalog();
                List<Order> orderList = new ArrayList<Order>(0);
                if (com.cakebackoffice.Model.Store.getLocalStore(context) != null)
                    orderList = server.getFollowingOrderList((int) Integer.parseInt(com.cakebackoffice.Model.Store.getLocalStore(context).getRemoteID().toString()));

                ourSQLiteOpenHelper.truncateTable();

                ourSQLiteOpenHelper.close();

                if (stores != null && stores.size() > 0)
                    SyncTaskManager.syncStores(context, stores);
                SyncTaskManager.syncCatalog(context, catalog);
                if (orderList != null && orderList.size() > 0)
                    SyncTaskManager.syncOrder(context, orderList);


            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }

            return 100;
        }

        @Override
        protected void onPreExecute() {
            progressDialog = ProgressDialog.show(getContext(), "Initialisation", "Catalog, Stores ...");
        }

        @Override
        protected void onPostExecute(Integer i) {
            progressDialog.dismiss();
            if (i == 0) {
                new AlertDialog.Builder(context).setMessage("Impossible de Synchroniser avec le serveur")
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.dismiss();
                            }
                        }).setPositiveButton("Dare to ... Try Again", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Intent intent = new Intent(context, MainActivity.class);
                        context.startActivity(intent);
                    }
                }).show();
            } else {
                //Si jamais tu trouve un truc à faire ^^

            }

        }
    }

    public static class SendOrder extends AsyncTask<com.cakebackoffice.Model.Order, Integer, Integer> {
        ProgressDialog progressDialog;
        Context context;
        private com.cakebackoffice.Model.Order order;

        public SendOrder(Context context) {
            this.context = context;
        }

        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }

        @Override
        protected Integer doInBackground(com.cakebackoffice.Model.Order... orders) {
            try {
                order = orders[0];
                CakeBackOfficeSoapClient server = new CakeBackOfficeSoapClient();
                if (order.getRemoteID() != null && order.getRemoteID() != 0) {
                    SimpleOrder orderToSend = new SimpleOrder(order);
                    server.updateOrder(orderToSend);
                } else {
                    if (order.getClient().getRemoteID() == null || order.getClient().getRemoteID() == 0
                            ) {
                        order.getClient().setRemoteID(Long.parseLong(server.createClient(new SimpleClient(order.getClient()))));
                    }
                    SimpleOrder orderToSend = new SimpleOrder(order);
                    orderToSend.idStore = com.cakebackoffice.Model.Store.getLocalStore(context).getRemoteID().intValue();
                    order.setRemoteID(((Integer) server.insertOrder(orderToSend)).longValue());
                    for (com.cakebackoffice.Model.UnitarySale unitarySale : order.getUnitarySaleList()) {
                        if (unitarySale.isProduct()) {
                            if (!server.addProductTypeToOrder(unitarySale.getProductType().getRemoteID().intValue(), order.getRemoteID().intValue()))
                                throw new Exception("Failed to addProductTypeToOrder");
                        } else {
                            //on verra
                        }
                    }

                    order.saveToDatabase(context);

                }
            } catch (Exception e) {

                return 0;
            }

            return 100;
        }

        @Override
        protected void onPreExecute() {
            progressDialog = ProgressDialog.show(getContext(), "Envoi vers le serveur", "Communication");
        }

        @Override
        protected void onPostExecute(Integer i) {
            progressDialog.dismiss();
            if (i == 0) {
                new AlertDialog.Builder(context).setMessage("Impossible de Synchroniser avec le serveur")
                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                dialogInterface.dismiss();
                            }
                        }).setPositiveButton("Dare to ... Try Again", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        new SendOrder(context).execute(new com.cakebackoffice.Model.Order[]{order});

                    }
                }).show();
            }
        }
    }
}
